/**
 * @(#)SystemProcessInstanceServiceImpl.java Sep 1, 2009
 *   
 * Copyright  (c) 2009-2010 Wilmar IT Service,  Inc.   
 * All  rights  reserved.   
 * TODO
 */

package com.wilmar.process.core.services.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.jbpm.api.ProcessDefinition;
import org.jbpm.api.ProcessEngine;
import org.jbpm.api.ProcessInstance;
import org.jbpm.api.model.ActivityCoordinates;

import com.wilmar.process.core.services.api.ISystemExecutionService;
import com.wilmar.process.core.services.api.ISystemProcessAuthorityService;
import com.wilmar.process.core.services.api.ISystemProcessInstanceService;
import com.wilmar.process.core.services.api.ISystemProcessLogService;
import com.wilmar.process.core.services.api.ISystemSubProcessInstanceRelationService;
import com.wilmar.process.entity.InstanceOperateOpinion;
import com.wilmar.process.entity.ProcessInstanceHelper;
import com.wilmar.process.entity.User;
import com.wilmar.process.entity.vo.ProcessInstanceVO;
import com.wilmar.process.enumerate.EnumProcessInstanceFixedVariableNameSet;
import com.wilmar.process.exception.DirtyDataException;
import com.wilmar.process.exception.ObjectNotFoundException;
import com.wilmar.process.exception.PermissionDeniedException;

/**
 * @author MaKuBEX Email:makubexnet@gmail.com
 * @version 2.0.1
 */
public class SystemProcessInstanceServiceImpl implements
		ISystemProcessInstanceService {

	private ProcessEngine processEngine;
	private ISystemProcessAuthorityService systemProcessAuthorityService;
	private ISystemProcessLogService systemProcessLogService;
	private ISystemExecutionService systemExecutionService;
	private ISystemSubProcessInstanceRelationService systemSubProcessInstanceRelationService;

	/**
	 * @return the systemProcessAuthorityService
	 */
	public ISystemProcessAuthorityService getSystemProcessAuthorityService() {
		return systemProcessAuthorityService;
	}

	/**
	 * @return the systemProcessLogService
	 */
	public ISystemProcessLogService getSystemProcessLogService() {
		return systemProcessLogService;
	}

	/**
	 * @param systemProcessAuthorityService
	 *            the systemProcessAuthorityService to set
	 */
	public void setSystemProcessAuthorityService(
			ISystemProcessAuthorityService systemProcessAuthorityService) {
		this.systemProcessAuthorityService = systemProcessAuthorityService;
	}

	/**
	 * @param systemProcessLogService
	 *            the systemProcessLogService to set
	 */
	public void setSystemProcessLogService(
			ISystemProcessLogService systemProcessLogService) {
		this.systemProcessLogService = systemProcessLogService;
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessInstanceService#startProcessInstanceById(java.lang.String,
	 *      com.wilmar.process.entity.User)
	 */
	public String startProcessInstanceById(String processDefinitionId, User user)
			throws PermissionDeniedException, DirtyDataException {
		ProcessDefinition pd = this.processEngine.getRepositoryService()
				.createProcessDefinitionQuery().processDefinitionId(
						processDefinitionId).uniqueResult();
		this.systemProcessAuthorityService.validateStartAuthority(pd.getKey(),
				user);
		ProcessInstanceHelper helper = new ProcessInstanceHelper();
		helper.setStarter(user);
		helper.setLastestOperator(user);
		helper.setProcessDefinitionKey(pd.getKey());
		helper.setProcessDefinitionId(processDefinitionId);
		helper.setProcessDefinitionName(pd.getName());
		Map<String, Object> varMap = new HashMap<String, Object>();
		varMap.put(
				EnumProcessInstanceFixedVariableNameSet.PROCESS_INSTANCE_HELPER
						.toString(), helper);
		ProcessInstance instance = this.processEngine.getExecutionService()
				.startProcessInstanceById(processDefinitionId, varMap);
		systemProcessLogService.saveStartLog(pd, this
				.getStartActivityNames(processDefinitionId), instance, user);
		return instance.getId();
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessInstanceService#startProcessInstanceByIdWithVariable(java.lang.String,
	 *      java.util.Map, com.wilmar.process.entity.User)
	 */
	public String startProcessInstanceByIdWithVariable(
			String processDefinitionId, Map<String, ?> variableMap, User user)
			throws PermissionDeniedException, DirtyDataException {
		ProcessDefinition pd = this.processEngine.getRepositoryService()
				.createProcessDefinitionQuery().processDefinitionId(
						processDefinitionId).uniqueResult();
		this.systemProcessAuthorityService.validateStartAuthority(pd.getKey(),
				user);
		ProcessInstanceHelper helper = new ProcessInstanceHelper();
		helper.setStarter(user);
		helper.setLastestOperator(user);
		helper.setProcessDefinitionKey(pd.getKey());
		helper.setProcessDefinitionId(processDefinitionId);
		helper.setProcessDefinitionName(pd.getName());
		Map<String, Object> varMap = new HashMap<String, Object>();
		varMap.putAll(variableMap);
		varMap.put(
				EnumProcessInstanceFixedVariableNameSet.PROCESS_INSTANCE_HELPER
						.toString(), helper);
		ProcessInstance instance = this.processEngine.getExecutionService()
				.startProcessInstanceById(processDefinitionId, varMap);
		systemProcessLogService.saveStartLog(pd, this
				.getStartActivityNames(processDefinitionId), instance, user);
		return instance.getId();
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessInstanceService#startProcessInstanceByKey(java.lang.String,
	 *      com.wilmar.process.entity.User)
	 */
	public String startProcessInstanceByKey(String processInstanceKey, User user)
			throws PermissionDeniedException, DirtyDataException {
		this.systemProcessAuthorityService.validateStartAuthority(
				processInstanceKey, user);
		ProcessInstanceHelper helper = new ProcessInstanceHelper();
		helper.setStarter(user);
		helper.setLastestOperator(user);
		helper.setProcessDefinitionKey(processInstanceKey);
		Map<String, Object> varMap = new HashMap<String, Object>();
		varMap.put(
				EnumProcessInstanceFixedVariableNameSet.PROCESS_INSTANCE_HELPER
						.toString(), helper);
		ProcessInstance instance = this.processEngine.getExecutionService()
				.startProcessInstanceByKey(processInstanceKey, varMap);
		ProcessDefinition pd = this.processEngine.getRepositoryService()
				.createProcessDefinitionQuery().processDefinitionId(
						instance.getProcessDefinitionId()).uniqueResult();
		systemProcessLogService.saveStartLog(pd, this.getStartActivityNames(pd
				.getId()), instance, user);
		return instance.getId();
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessInstanceService#startProcessInstanceByKeyWithVariable(java.lang.String,
	 *      java.util.Map, com.wilmar.process.entity.User)
	 */
	public String startProcessInstanceByKeyWithVariable(
			String processInstanceKey, Map<String, ?> variableMap, User user)
			throws PermissionDeniedException, DirtyDataException {
		this.systemProcessAuthorityService.validateStartAuthority(
				processInstanceKey, user);
		ProcessInstanceHelper helper = new ProcessInstanceHelper();
		helper.setStarter(user);
		helper.setLastestOperator(user);
		helper.setProcessDefinitionKey(processInstanceKey);
		Map<String, Object> varMap = new HashMap<String, Object>();
		varMap.putAll(variableMap);
		varMap.put(
				EnumProcessInstanceFixedVariableNameSet.PROCESS_INSTANCE_HELPER
						.toString(), helper);
		ProcessInstance instance = this.processEngine.getExecutionService()
				.startProcessInstanceByKey(processInstanceKey, varMap);
		ProcessDefinition pd = this.processEngine.getRepositoryService()
				.createProcessDefinitionQuery().processDefinitionId(
						instance.getProcessDefinitionId()).uniqueResult();
		systemProcessLogService.saveStartLog(pd, this.getStartActivityNames(pd
				.getId()), instance, user);
		return instance.getId();
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessInstanceService#stopProcessInstanceById(java.lang.String,
	 *      com.wilmar.process.entity.User)
	 */
	public synchronized void stopProcessInstanceById(String processInstanceId,
			User user) throws PermissionDeniedException {
		ProcessInstance processInstance = this.processEngine
				.getExecutionService().findProcessInstanceById(
						processInstanceId);
		if (processInstance != null && !processInstance.isSuspended()) {
			ProcessInstanceHelper helper = null;
			try {
				helper = this.getProcessInstanceHelperById(processInstanceId);
			} catch (ObjectNotFoundException e) {
				e.printStackTrace();
			}
			if (!user.equals(helper.getStarter()))
				throw new PermissionDeniedException(
						"You are not the starter of this process instance!");
			else {
				this.processEngine.getExecutionService().endProcessInstance(
						processInstanceId, ProcessInstance.STATE_ENDED);
			}
		}
	}

	private String getStartActivityNames(String processDefinitionId) {
		List<String> startNameList = this.processEngine.getRepositoryService()
				.getStartActivityNames(processDefinitionId);
		return startNameList.get(0);
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessInstanceService#getActivityCoordinates(java.lang.String)
	 */
	public Set<ActivityCoordinates> getActivityCoordinates(
			String processInstanceId) throws ObjectNotFoundException {
		ProcessInstance pi = this.processEngine.getExecutionService()
				.findProcessInstanceById(processInstanceId);
		if (pi == null)
			throw new ObjectNotFoundException("Process instance : "
					+ processInstanceId + " has ended!");
		Set<String> activityNames = pi.findActiveActivityNames();
		Set<ActivityCoordinates> resultMap = new HashSet<ActivityCoordinates>();
		for (String activityName : activityNames) {
			resultMap.add(this.processEngine.getRepositoryService()
					.getActivityCoordinates(pi.getProcessDefinitionId(),
							activityName));
		}
		return resultMap;
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessInstanceService#suspendProcessInstanceById(java.lang.String,
	 *      com.wilmar.process.entity.User)
	 */
	public void suspendProcessInstanceById(String processInstanceId, User user)
			throws PermissionDeniedException, ObjectNotFoundException {
		ProcessInstance pi = this.processEngine.getExecutionService()
				.findProcessInstanceById(processInstanceId);
		if (pi == null)
			throw new ObjectNotFoundException("Process instance : "
					+ processInstanceId + " has ended!");
		ProcessInstanceHelper helper = this
				.getProcessInstanceHelperById(processInstanceId);
		if (!user.equals(helper.getStarter()))
			throw new PermissionDeniedException(
					"You are not the starter of this process instance!");
		else {
			// TODO;
		}
	}

	/**
	 * @see com.wilmar.process.core.services.api.IBaseService#convertToVO(java.lang.Object)
	 */
	public ProcessInstanceVO convertToVO(ProcessInstance entity) {
		ProcessInstanceVO vo = new ProcessInstanceVO(entity);
		return vo;
	}

	/**
	 * @see com.wilmar.process.core.services.api.IBaseService#convertToVOList(java.util.List)
	 */
	public List<ProcessInstanceVO> convertToVOList(
			Collection<ProcessInstance> entityCollection) {
		List<ProcessInstanceVO> voList = new ArrayList<ProcessInstanceVO>(
				entityCollection.size());
		for (ProcessInstance instance : entityCollection) {
			voList.add(this.convertToVO(instance));
		}
		return voList;
	}

	/**
	 * @throws ObjectNotFoundException
	 * @see com.wilmar.process.core.services.api.ISystemProcessInstanceService#getProcessInstanceHelperById(java.lang.String)
	 */
	public ProcessInstanceHelper getProcessInstanceHelperById(
			String processInstanceId) throws ObjectNotFoundException {
		ProcessInstanceHelper helper = (ProcessInstanceHelper) this
				.getVariable(
						processInstanceId,
						EnumProcessInstanceFixedVariableNameSet.PROCESS_INSTANCE_HELPER
								.toString());
		return helper;
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessInstanceService#getVariable(java.lang.String,
	 *      java.lang.String)
	 */
	public Object getVariable(String processInstanceId, String variableName)
			throws ObjectNotFoundException {
		Object value = this.processEngine.getExecutionService().getVariable(
				processInstanceId, variableName);
		if (value == null)
			throw new ObjectNotFoundException("There is not a variable named:"
					+ variableName + " in process instance:"
					+ processInstanceId);
		return value;
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessInstanceService#
	 *      startProcessInstanceById(java.lang.String, java.lang.String,
	 *      com.wilmar.process.entity.User)
	 */
	public String startProcessInstanceById(String processDefinitionId,
			String processInstanceKey, User user)
			throws PermissionDeniedException, DirtyDataException {
		if (processInstanceKey == null
				|| processInstanceKey.trim().length() == 0)
			return this.startProcessInstanceById(processDefinitionId, user);
		ProcessDefinition pd = this.processEngine.getRepositoryService()
				.createProcessDefinitionQuery().processDefinitionId(
						processDefinitionId).uniqueResult();
		this.systemProcessAuthorityService.validateStartAuthority(pd.getKey(),
				user);
		ProcessInstanceHelper helper = new ProcessInstanceHelper();
		helper.setStarter(user);
		helper.setLastestOperator(user);
		helper.setProcessDefinitionKey(pd.getKey());
		helper.setProcessDefinitionId(processDefinitionId);
		helper.setProcessDefinitionName(pd.getName());
		Map<String, Object> varMap = new HashMap<String, Object>();
		varMap.put(
				EnumProcessInstanceFixedVariableNameSet.PROCESS_INSTANCE_HELPER
						.toString(), helper);
		ProcessInstance instance = this.processEngine.getExecutionService()
				.startProcessInstanceById(processDefinitionId, varMap,
						processInstanceKey);
		systemProcessLogService.saveStartLog(pd, this
				.getStartActivityNames(processDefinitionId), instance, user);
		return instance.getId();
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessInstanceService#
	 *      startProcessInstanceByIdWithVariable(java.lang.String,
	 *      java.lang.String, java.util.Map, com.wilmar.process.entity.User)
	 */
	public String startProcessInstanceByIdWithVariable(
			String processDefinitionId, String processInstanceKey,
			Map<String, ?> variableMap, User user)
			throws PermissionDeniedException, DirtyDataException {
		if (processInstanceKey == null
				|| processInstanceKey.trim().length() == 0)
			return this.startProcessInstanceByIdWithVariable(
					processDefinitionId, variableMap, user);
		ProcessDefinition pd = this.processEngine.getRepositoryService()
				.createProcessDefinitionQuery().processDefinitionId(
						processDefinitionId).uniqueResult();
		this.systemProcessAuthorityService.validateStartAuthority(pd.getKey(),
				user);
		ProcessInstanceHelper helper = new ProcessInstanceHelper();
		helper.setStarter(user);
		helper.setLastestOperator(user);
		helper.setProcessDefinitionKey(pd.getKey());
		helper.setProcessDefinitionId(processDefinitionId);
		helper.setProcessDefinitionName(pd.getName());
		Map<String, Object> varMap = new HashMap<String, Object>();
		varMap.putAll(variableMap);
		varMap.put(
				EnumProcessInstanceFixedVariableNameSet.PROCESS_INSTANCE_HELPER
						.toString(), helper);
		ProcessInstance instance = this.processEngine.getExecutionService()
				.startProcessInstanceById(processDefinitionId, varMap,
						processInstanceKey);
		systemProcessLogService.saveStartLog(pd, this
				.getStartActivityNames(processDefinitionId), instance, user);
		return instance.getId();
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessInstanceService#
	 *      startProcessInstanceByKey(java.lang.String, java.lang.String,
	 *      com.wilmar.process.entity.User)
	 */
	public String startProcessInstanceByKey(String processDefinitionKey,
			String processInstanceKey, User user)
			throws PermissionDeniedException, DirtyDataException {
		if (processInstanceKey == null
				|| processInstanceKey.trim().length() == 0)
			return this.startProcessInstanceByKey(processDefinitionKey, user);
		this.systemProcessAuthorityService.validateStartAuthority(
				processDefinitionKey, user);
		ProcessInstanceHelper helper = new ProcessInstanceHelper();
		helper.setStarter(user);
		helper.setLastestOperator(user);
		helper.setProcessDefinitionKey(processDefinitionKey);
		Map<String, Object> varMap = new HashMap<String, Object>();
		varMap.put(
				EnumProcessInstanceFixedVariableNameSet.PROCESS_INSTANCE_HELPER
						.toString(), helper);
		ProcessInstance instance = this.processEngine.getExecutionService()
				.startProcessInstanceByKey(processDefinitionKey, varMap,
						processInstanceKey);
		ProcessDefinition pd = this.processEngine.getRepositoryService()
				.createProcessDefinitionQuery().processDefinitionId(
						instance.getProcessDefinitionId()).uniqueResult();
		systemProcessLogService.saveStartLog(pd, this.getStartActivityNames(pd
				.getId()), instance, user);
		return instance.getId();
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessInstanceService#
	 *      startProcessInstanceByKeyWithVariable(java.lang.String,
	 *      java.lang.String, java.util.Map, com.wilmar.process.entity.User)
	 */
	public String startProcessInstanceByKeyWithVariable(
			String processDefinitionKey, String processInstanceKey,
			Map<String, ?> variableMap, User user)
			throws PermissionDeniedException, DirtyDataException {
		if (processInstanceKey == null
				|| processInstanceKey.trim().length() == 0)
			return this.startProcessInstanceByKeyWithVariable(
					processDefinitionKey, variableMap, user);
		this.systemProcessAuthorityService.validateStartAuthority(
				processDefinitionKey, user);
		ProcessInstanceHelper helper = new ProcessInstanceHelper();
		helper.setStarter(user);
		helper.setLastestOperator(user);
		helper.setProcessDefinitionKey(processDefinitionKey);
		Map<String, Object> varMap = new HashMap<String, Object>();
		varMap.putAll(variableMap);
		varMap.put(
				EnumProcessInstanceFixedVariableNameSet.PROCESS_INSTANCE_HELPER
						.toString(), helper);
		ProcessInstance instance = this.processEngine.getExecutionService()
				.startProcessInstanceByKey(processDefinitionKey, varMap,
						processInstanceKey);
		ProcessDefinition pd = this.processEngine.getRepositoryService()
				.createProcessDefinitionQuery().processDefinitionId(
						instance.getProcessDefinitionId()).uniqueResult();
		systemProcessLogService.saveStartLog(pd, this.getStartActivityNames(pd
				.getId()), instance, user);
		return instance.getId();
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessInstanceService#findById(java.lang.String)
	 */
	public ProcessInstance getDetailById(String processInstanceId)
			throws ObjectNotFoundException {
		ProcessInstance processInstance = this.processEngine
				.getExecutionService().findProcessInstanceById(
						processInstanceId);
		if (processInstance == null)
			throw new ObjectNotFoundException(
					"There is no process instance's id is :"
							+ processInstanceId);
		return processInstance;
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessInstanceService#createOrUpdateVariable(java.lang.String,
	 *      java.lang.Object)
	 */
	public void createOrUpdateVariable(String processInstanceId, String name,
			Object value) {
		try {
			EnumProcessInstanceFixedVariableNameSet.valueOf(name);
		} catch (Exception e) {
			this.processEngine.getExecutionService().setVariable(
					processInstanceId, name, value);
		}
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessInstanceService#createOrUpdateVariables(java.lang.String,
	 *      java.util.Map)
	 */
	public void createOrUpdateVariables(String processInstanceId,
			Map<String, ?> variableMap) {
		Iterator<String> iter = variableMap.keySet().iterator();
		while (iter.hasNext()) {
			String vname = iter.next();
			try {
				EnumProcessInstanceFixedVariableNameSet.valueOf(vname);
				variableMap.remove(vname);
			} catch (Exception e) {
			}
		}
		this.processEngine.getExecutionService().setVariables(
				processInstanceId, variableMap);
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessInstanceService#getProcessDescription(java.lang.String)
	 */
	public String getProcessDescription(String processInstanceId)
			throws ObjectNotFoundException {
		ProcessInstance pi = this.processEngine.getExecutionService()
				.findProcessInstanceById(processInstanceId);
		if (pi == null)
			throw new ObjectNotFoundException(
					"Here is no process instance, the id is:"
							+ processInstanceId);
		String processDefinitionId = pi.getProcessDefinitionId();
		ProcessDefinition pd = this.processEngine.getRepositoryService()
				.createProcessDefinitionQuery().processDefinitionId(
						processDefinitionId).uniqueResult();
		return pd.getDescription();
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessInstanceService#getDetailByKey(java.lang.String,
	 *      java.lang.String)
	 */
	public Set<ProcessInstance> getDetailByKey(String processDefinitionKey,
			String processInstanceKey) throws ObjectNotFoundException {
		List<ProcessDefinition> pdList = this.processEngine
				.getRepositoryService().createProcessDefinitionQuery()
				.processDefinitionKey(processDefinitionKey).list();
		Set<ProcessInstance> result = new HashSet<ProcessInstance>();
		for (ProcessDefinition pd : pdList) {
			String pdid = pd.getId();
			List<ProcessInstance> pilist = this.processEngine
					.getExecutionService().createProcessInstanceQuery()
					.processInstanceKey(processInstanceKey)
					.processDefinitionId(pdid).list();
			if (pilist != null && !pilist.isEmpty())
				result.addAll(pilist);
		}
		if (result.isEmpty())
			throw new ObjectNotFoundException(
					"There is no process instance's key is :"
							+ processInstanceKey + " in process definition : "
							+ processDefinitionKey);
		return result;
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessInstanceService#getDetailByKey(java.lang.String)
	 */
	public Set<ProcessInstance> getDetailByKey(String processInstanceKey)
			throws ObjectNotFoundException {
		List<ProcessInstance> pilist = this.processEngine.getExecutionService()
				.createProcessInstanceQuery().processInstanceKey(
						processInstanceKey).list();
		if (pilist.isEmpty())
			throw new ObjectNotFoundException(
					"There is no process instance's key is :"
							+ processInstanceKey);
		return new HashSet<ProcessInstance>(pilist);
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessInstanceService#signalProcessInstanceById(java.lang.String,
	 *      com.wilmar.process.entity.User,
	 *      com.wilmar.process.entity.InstanceOperateOpinion)
	 */
	public synchronized ProcessInstance signalProcessInstanceById(
			String ProcessInstanceId, User user, InstanceOperateOpinion opinion) {
		return this.systemExecutionService.signalExecutionById(
				ProcessInstanceId, user, opinion);
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessInstanceService#signalProcessInstanceById(java.lang.String,
	 *      java.util.Map, com.wilmar.process.entity.User,
	 *      com.wilmar.process.entity.InstanceOperateOpinion)
	 */
	public synchronized ProcessInstance signalProcessInstanceById(
			String ProcessInstanceId, Map<String, ?> variables, User user,
			InstanceOperateOpinion opinion) {
		return this.systemExecutionService.signalExecutionById(
				ProcessInstanceId, variables, user, opinion);
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessInstanceService#signalProcessInstanceById(java.lang.String,
	 *      java.lang.String, com.wilmar.process.entity.User,
	 *      com.wilmar.process.entity.InstanceOperateOpinion)
	 */
	public synchronized ProcessInstance signalProcessInstanceById(
			String ProcessInstanceId, String signalName, User user,
			InstanceOperateOpinion opinion) {
		return this.systemExecutionService.signalExecutionById(
				ProcessInstanceId, signalName, user, opinion);
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessInstanceService#signalProcessInstanceById(java.lang.String,
	 *      java.util.Map, java.lang.String, com.wilmar.process.entity.User,
	 *      com.wilmar.process.entity.InstanceOperateOpinion)
	 */
	public synchronized ProcessInstance signalProcessInstanceById(
			String ProcessInstanceId, Map<String, ?> variables,
			String signalName, User user, InstanceOperateOpinion opinion) {
		return this.systemExecutionService.signalExecutionById(
				ProcessInstanceId, variables, signalName, user, opinion);
	}

	/**
	 * @return the systemExecutionService
	 */
	public ISystemExecutionService getSystemExecutionService() {
		return systemExecutionService;
	}

	/**
	 * @param systemExecutionService
	 *            the systemExecutionService to set
	 */
	public void setSystemExecutionService(
			ISystemExecutionService systemExecutionService) {
		this.systemExecutionService = systemExecutionService;
	}

	/**
	 * @return the processEngine
	 */
	public ProcessEngine getProcessEngine() {
		return processEngine;
	}

	/**
	 * @param processEngine
	 *            the processEngine to set
	 */
	public void setProcessEngine(ProcessEngine processEngine) {
		this.processEngine = processEngine;
	}

	/**
	 * @return the systemSubProcessInstanceRelationService
	 */
	public ISystemSubProcessInstanceRelationService getSystemSubProcessInstanceRelationService() {
		return systemSubProcessInstanceRelationService;
	}

	/**
	 * @param systemSubProcessInstanceRelationService
	 *            the systemSubProcessInstanceRelationService to set
	 */
	public void setSystemSubProcessInstanceRelationService(
			ISystemSubProcessInstanceRelationService systemSubProcessInstanceRelationService) {
		this.systemSubProcessInstanceRelationService = systemSubProcessInstanceRelationService;
	}

}
